筆記目錄

Skip to content

如何在 .NET 使用 AutoMapper

TLDR

  • AutoMapper 透過 Reflection 簡化 DTO 與 Entity 之間的屬性賦值,減少重複程式碼。
  • MapperConfiguration 應維持單例(Singleton),建議在應用程式啟動時(如 Program.cs)進行配置。
  • 務必使用 config.AssertConfigurationIsValid() 驗證映射設定,確保所有 Destination 欄位皆有對應來源。
  • 使用 Profile 類別將映射邏輯模組化,避免配置過於龐大。
  • 針對複雜映射,可透過 ForMember 進行條件判斷、忽略欄位或自定義轉換邏輯。
  • 使用 ReverseMap() 可簡化雙向轉換,但需注意複雜邏輯需搭配 ForPath 定義反向規則。
  • 整合 Dependency Injection 需安裝 AutoMapper.Extensions.Microsoft.DependencyInjection 套件。

AutoMapper 基礎配置與驗證

在 .NET 應用程式中,為了實現關注點分離,常需在不同層級間轉換 DTO。AutoMapper 透過 MapperConfiguration 定義映射規則,並透過 IMapper 執行轉換。

核心使用方式

什麼情況下會遇到這個問題:當需要將一個物件的屬性值複製到另一個型別的物件時。

csharp
// 建立 Configuration 設定 class 之間的映射關係
var config = new MapperConfiguration(cfg => {
    cfg.CreateMap<Order, OrderDto>();
});

// 驗證 Configuration 的設置,若 Destination 有的 Member 在 Source 找不到對應,會拋出 AutoMapperConfigurationException
config.AssertConfigurationIsValid();

// 建立 Mapper
var mapper = config.CreateMapper();

// 執行映射
var dest = mapper.Map<Destination>(source);

映射規則設定

為了保持程式碼整潔,建議將映射設定封裝於 Profile 類別中。

模組化設定

什麼情況下會遇到這個問題:當專案中存在大量類別映射,導致 Program.csStartup.cs 過於臃腫時。

csharp
public class OtherProfile : Profile {
    public OtherProfile() {
        CreateMap<Source1, Destination1>();
        // 全域型別轉換(例如:統一處理字串去空白)
        CreateMap<string?, string?>().ConvertUsing(x => x == null ? x : x.Trim());
    }
}

屬性映射進階控制

什麼情況下會遇到這個問題:當 Source 與 Destination 的屬性名稱不一致,或需要根據特定條件決定是否映射時。

csharp
var config = new MapperConfiguration(cfg => {
    cfg.CreateMap<Source, Destination>()
        // 忽略特定欄位
        .ForMember(desc => desc.Prop1, opt => opt.Ignore())
        // 指定欄位對應
        .ForMember(dest => dest.DestProp2, opt => opt.MapFrom(src => src.SourceProp2))
        // 設定條件映射
        .ForMember(dest => dest.IntProp4, opt => opt.Condition(src => (src.IntProp4 >= 0)))
        // 設定預設值
        .ForMember(dest => dest.Prop5, opt => opt.NullSubstitute("Other Value"));
});

反向映射與注意事項

使用 ReverseMap() 可以快速建立雙向映射,但需注意以下限制:

  • 複雜的轉換邏輯需使用 ForPath 定義反向規則。
  • AssertConfigurationIsValid() 無法驗證反向映射的正確性。
csharp
var config = new MapperConfiguration(cfg => {
    cfg.CreateMap<Source, Destination>()
        .ForMember(dest => dest.Prop5, opt => opt.MapFrom(src => src.Prop3 + "," + src.Prop4))
        .ReverseMap()
        .ForPath(s => s.Prop3, opt => opt.MapFrom(src => src.Prop5.Split(',')[0]));
});

整合 Dependency Injection

什麼情況下會遇到這個問題:在現代 .NET 應用程式中,需要透過 DI 容器管理 IMapper 實例。

需安裝 NuGet 套件 AutoMapper.Extensions.Microsoft.DependencyInjection

csharp
// 在 Program.cs 中註冊
builder.Services.AddAutoMapper(typeof(Program));

// 在 Controller 或 Service 中使用
public class EmployeesController {
    private readonly IMapper _mapper;
    public EmployeesController(IMapper mapper) => _mapper = mapper;
}

異動歷程

  • 2022-10-24 初版文件建立。